#include "QtUI/OpenProjectCommand.qth"
#include "QtUI/OpenProjectCommand.moh"
#include "QtUI/ExistingProjectListDialog.qth"
#include "QtUI/ExistingProjectListWidget.qth"
#include "QtUI/CloseProjectCommand.qth"
#include "QtUI/ProjectCommands.qth"
#include "AbsUI/UIConfigurationCenter.hpp"
#include "Model/Project.hpp"
#include "Storage/ConnectionConfig.hpp"
#include "Storage/StorageFactory.hpp"
#include "Storage/ProjectStorage.hpp"
#include "Ctrl/ControlCenter.hpp"
#include <QtGui/QMessageBox>

namespace QtUI
{

OpenProjectCommand::OpenProjectCommand( QAction* pBoundAction)
	: UICommandBase( pBoundAction)
{
}

// ---------------------------------------------------------------------------------------------------------------------

bool OpenProjectCommand::execute( bool )
{
	ExistingProjectListDialog dlg( 
		AbsUI::UIConfigurationCenter::uiConfigCenter().connCfgCollection(), 
		AbsUI::UIConfigurationCenter::uiConfigCenter().uiFactory());
	
	// The dialog display and action in case of not cancelling the opening is put in a while loop. This loop executes 
	//	until the project opens successfuly or the user presses cancel. In case of errors, the error is reported and the 
	//	open project dialog is displayed again, allowing the user to correct/retry opening the project.
	while( true)
	{
		int result = dlg.exec();

		if( result == QDialog::Accepted)
		{
			using namespace Model;
			using namespace Storage;

			try
			{
				const ConnectionConfig* pConnConfig = dlg.prjListWidget().selectedConnectionConfig();
				boost::any projectId = dlg.prjListWidget().selectedProjectID();
				if( NULL == pConnConfig || projectId.empty())
				{
					// TODO: How should we react if no connection and no project is selected?
					return false;
				}

				std::auto_ptr< StorageFactory> pStoragePolicyFactory( pConnConfig->createStorageFactory());
				std::auto_ptr< Project> pNewProject( pStoragePolicyFactory->getProjectStorage().loadProject( projectId));

				// Close current project
				CloseProjectCommand& closeCmd = dynamic_cast< CloseProjectCommand&>( ProjectCommands::getCloseProjectCommand());
				if( closeCmd.canCloseProject())
				{
					Ctrl::ControlCenter::instance().prjController().setControlledProject( 
						pNewProject.release(), pStoragePolicyFactory.release());
					return true; // No need to reopen the dialog.
				}
				// ELSE:
				// If the current project couldn't be saved or the user have chosen not to close current project, then 
				// try open project again.
			}
			catch( std::exception& e)
			{
				QMessageBox::critical( 
					NULL, 
					tr( "Open Project"), 
					tr( "There was an error while opening the project:\n") + QString( e.what()));
				return false;
			}
		} 
		else
		{ 
			// Cancelled
			assert( result == QDialog::Rejected);
			return false;
		}
	} // while( true)
}

} // namespace QtUI
